using System;
using System.Collections.Generic;
using System.Text;
using InfoJetSoft.Service.XPath;

//CID 0164 //2008.12.13 //Begin
namespace InfoJetSoft.Service.XPath.Exprs
{
	/// <summary>
	/// Summary description for AndExpr.
	/// </summary>
    public class AndExpr : IExpr
	{
        private List<IExpr> _eqaulList = null;

		public AndExpr()
		{
			//
			// TODO: Add constructor logic here
			//
        }

        public object Evaluate(ExprContext context)
        {
            //CID 0807 //2011.02.28 //Begin
            object leftValue = null;
            for (int i = 0; i < this._eqaulList.Count; i++)
            {
                IExpr expr = this._eqaulList[i];
                if (expr is OperatorExpr)
                {
                    //CID 0810 //2011.02.28 //Begin
                    bool boolLeftValue = BooleanFunctions.boolean(leftValue);
                    leftValue = boolLeftValue;
                    if (!context.Calculator.FullPath)
                    {
                        if (!boolLeftValue)
                        {
                            return false;
                        }
                    }
                    //CID 0810 //2011.02.28 //End
                    OperatorExpr oper = (OperatorExpr)expr;
                    i++;
                    IExpr nextExpr = this._eqaulList[i];
                    object rightValue = nextExpr.Evaluate(context);
                    if (oper.Operator == Operator.And)
                    {
                        leftValue = this.And(leftValue, rightValue);
                    }
                    else
                    {
                        throw new Exception("Unsupported operator: " + oper.Operator);
                    }
                }
                else
                {
                    if (leftValue == null)
                    {
                        leftValue = expr.Evaluate(context);
                    }
                    else
                    {
                        throw new Exception("Unsupported expr order");
                    }
                }
            }
            return leftValue;
            //CID 0807 //2011.02.28 //End
        }

        //CID 0866 //2011.04.01 //Begin
        public void Visit(IExprVisitor visitor)
        {
            for (int i = 0; i < this._eqaulList.Count; i++)
            {
                IExpr expr = this._eqaulList[i];
                expr.Visit(visitor);
            }
        }
        //CID 0866 //2011.04.01 //End

        //CID 0807 //2011.02.28 //Begin
        private bool And(object value1, object value2)
        {
            bool bool1 = BooleanFunctions.boolean(value1);
            bool bool2 = BooleanFunctions.boolean(value2);
            if (bool1 && bool2)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        //CID 0807 //2011.02.28 //End

        public void Print(StringBuilder buffer)
        {
            foreach (IExpr expr in this._eqaulList)
            {
                expr.Print(buffer);
            }
        }

        public static IExpr Parse(ExprParser parser)
		{
			IExpr equalityExpr = EqualityExpr.Parse( parser );
			if( equalityExpr != null )
			{
                List<IExpr> list = new List<IExpr>();
				list.Add( equalityExpr );

                OperatorExpr andOperator = OperatorExpr.ParseAndOperator(parser);
				while( andOperator != null )
				{
                    list.Add(andOperator);

                    IExpr nextEqualityExpr = EqualityExpr.Parse(parser);
					if( nextEqualityExpr == null )
					{
						throw new Exception( "Cannot parse " + parser.XPath );
					}
					list.Add( nextEqualityExpr );
					
					andOperator = OperatorExpr.ParseAndOperator( parser );
				}

                if (list.Count > 1)
                {
                    AndExpr andExpr = new AndExpr();
                    andExpr._eqaulList = list;
                    return andExpr;
                }
                else
                {
                    return equalityExpr;
                }
			}
			return null;
		}
	}
}
//CID 0164 //2008.12.13 //End